package pers.zh.parking.common;

import android.app.Application;
import android.net.ParseException;
import android.text.TextUtils;

import com.google.gson.JsonParseException;
import com.jess.arms.integration.EventBusManager;
import com.jess.arms.mvp.IView;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;

import io.reactivex.observers.ResourceObserver;
import pers.zh.parking.R;
import pers.zh.parking.config.GlobalConfiguration;
import pers.zh.parking.utils.MyUtils;
import pers.zjc.commonlibs.util.NetworkUtils;
import pers.zjc.commonlibs.util.StringUtils;
import retrofit2.HttpException;

public abstract class BaseObserver<T extends BaseResponse> extends ResourceObserver<T> {

    //对应HTTP的状态码
    private static final int BAD_REQUEST = 400;
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;

    protected IView mView;
    private String mErrorMessage;
    private Application mApp = GlobalConfiguration.getInstance();

    public BaseObserver(IView mView) {
        this.mView = mView;
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (!MyUtils.isNetWorkAvailable()) {
            mView.showMessage(mApp.getString(R.string.network_unavailable_tip));
            onComplete();
        }
        mView.showLoading();
    }

    @Override
    public void onNext(T t) {
        switch (t.getCode()) {
            case Const.HttpStatusCode.HttpStatus_200:
                onSuccess(t);
                break;
            case Const.HttpStatusCode.HttpStatus_401:
            default:
                onError(new ApiException(StringUtils.isEmpty(t.getMsg()) ? mApp.getString(R.string.error) : t.getMsg(), t.getCode()));
                break;
        }
    }

    @Override
    public void onError(Throwable e) {
        if (e instanceof ConnectException ||  e instanceof UnknownHostException) {   //   连接错误
            onException(ExceptionReason.CONNECT_ERROR);
        } else if ( e instanceof InterruptedIOException) {  //  连接超时
            onException(ExceptionReason.CONNECT_TIMEOUT);
        } else if (e instanceof HttpException) {    // HTTP错误
            HttpException httpException = (HttpException) e;
            switch(httpException.code()){
                case UNAUTHORIZED:
                case FORBIDDEN:
                    mErrorMessage = "鉴权失败";          //权限错误，需要实现
                    break;
                case BAD_REQUEST:
                case NOT_FOUND:
                case REQUEST_TIMEOUT:
                case GATEWAY_TIMEOUT:
                case INTERNAL_SERVER_ERROR:
                case BAD_GATEWAY:
                case SERVICE_UNAVAILABLE:
                default:
                    onException(ExceptionReason.BAD_NETWORK);  //均视为网络错误
                    break;
            }
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {   //  解析错误
            onException(ExceptionReason.PARSE_ERROR);
        } else if (e instanceof ApiException) {
            if (StringUtils.isEmpty(e.getMessage())) {
                onException(ExceptionReason.UNKNOWN_ERROR);
            } else {
                mErrorMessage = e.getMessage();
                mView.showMessage(mErrorMessage);
            }
        } else {    // 未知错误
            onException(ExceptionReason.UNKNOWN_ERROR);
        }
        onComplete();
    }

    protected void onException(ExceptionReason reason) {
        switch (reason) {
            case PARSE_ERROR:
                mErrorMessage = mApp.getString(R.string.error_parse);
                break;
            case BAD_NETWORK:
                mErrorMessage = mApp.getString(R.string.error_server_error);
                break;
            case CONNECT_ERROR:
                mErrorMessage = mApp.getString(R.string.error_fail_to_connect);
                break;
            case CONNECT_TIMEOUT:
                mErrorMessage = mApp.getString(R.string.error_connect_time_out);
                break;
            case UNKNOWN_ERROR:
            default:
                mErrorMessage = mApp.getString(R.string.error_unknown);
                break;
        }
        mView.showMessage(mErrorMessage);
        onComplete();
    }

    @Override
    public void onComplete() {
        if (mView != null) {
            mView.hideLoading();
        }
    }

    /**
     * 成功回调
     * @param t
     */
    public abstract void onSuccess(T response);

    /**
     * 服务端返回错误回调：服务器返回数据，但响应码不为200
     * @param t
     */
    public void onError(T t) {
        String msg = t.getMsg();
        if (TextUtils.isEmpty(msg)) {
            mView.showMessage(mApp.getString(R.string.error_server_error));
        } else {
            mView.showMessage(t.getMsg());
        }

    }

    /**
     * 请求网络失败原因
     */
    public enum ExceptionReason {
        /**
         * 解析数据失败
         */
        PARSE_ERROR,
        /**
         * 网络问题
         */
        BAD_NETWORK,
        /**
         * 连接错误
         */
        CONNECT_ERROR,
        /**
         * 连接超时
         */
        CONNECT_TIMEOUT,
        /**
         * 未知错误
         */
        UNKNOWN_ERROR,
    }

}
